package com.dq.context.init;

import com.dq.cache.constant.CacheConstant;
import com.dq.cache.J2CacheUtils;
import com.dq.context.Constant;
import com.dq.exception.customException.AdminException;
import com.dq.domain.address.NullSysRegion;
import com.dq.domain.address.SysRegion;
import com.dq.domain.base.AbstractEntity;
import com.dq.domain.category.NullCategory;
import com.dq.domain.evaluation.EvaluationTemplate;
import com.dq.domain.sys.macro.NullSysMacro;
import com.dq.domain.sys.menu.NullSysMenu;
import com.dq.domain.sys.menu.SysMenu;
import com.dq.domain.sys.role.SysRole;
import com.dq.domain.sys.role.SysRoleMenu;
import com.dq.domain.sys.role.SysUserRole;
import com.dq.domain.sys.section.SysSection;
import com.dq.domain.sys.user.user.BossUser;
import com.dq.domain.setup.TrackGenerateRateSet;
import com.dq.repository.*;
import com.dq.repository.set.TrackGenerateRateSetRepository;
import com.dq.service.BaseServices;
import com.dq.utils.ListUtils;
import lombok.extern.java.Log;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.dq.context.Constant.ORDERS_SUFF_COUNT;

@Component
@Log
public class InitDataListener extends BaseServices implements ApplicationListener<ApplicationStartedEvent> {

    @Autowired
    NullSysMacroRepository nullSysMacroRepository;
    @Autowired
    NullSysMenuRepository nullSysMenuRepository;
    @Autowired
    NullCategoryRepository nullCategoryRepository;

    @Autowired
    NullSysRegionRepository nullSysRegionRepository;
    @Autowired
    TrackGenerateRateSetRepository trackGenerateRateSetRepository;

    public List<SysRegion> sysRegionEntityList;

    @Override
    public void onApplicationEvent(ApplicationStartedEvent event) {
        initSysSection();

        initNullCategory();

        initSysMenu();

        initUser();

        initUserRole();

        initRoleMenu();

        initEvaluationTemplate();

        initNullSysMacro();

        initNullSysRegion();

        initTrackRateSet();

    }

    /** 生成默认顶级组织部门 */
    private void initSysSection() {
        List<SysSection> all = sysSectionRepository.findAll();
        if(all.size() <= 0) {
            SysSection section = new SysSection(AbstractEntity.generyDatetimeAndRandomNum(Constant.ORDERS_SUFF_COUNT), "总公司", "总公司", 0,  SysMenu.Status.on, "");
            sysSectionRepository.save(section);
        }
    }

    /** 生成默认系统菜单/子菜单 */
    private void initSysMenu() {
        // 适应初始项目框架, 需要有一个 NullSysMenu, 区分boss/门店菜单根据 Genre字段
        List<NullSysMenu> nullSysMenus = nullSysMenuRepository.findByGenre(SysMenu.Genre.boss);
        NullSysMenu nullSysMenu = null;
        if (nullSysMenus.isEmpty()) {
            nullSysMenu = new NullSysMenu();
            nullSysMenu.setType(SysMenu.Type.list);
            nullSysMenu.setGenre(SysMenu.Genre.boss);
            nullSysMenu.setOrderNum(0);
            nullSysMenu = nullSysMenuRepository.save(nullSysMenu);
            return;
        }else {
            nullSysMenu = nullSysMenus.get(0);
        }
        J2CacheUtils.put("NullSysMenu", nullSysMenu);

        List<String> strings = getStrings();
        List<SysMenu> sysMenus = sysMenuRepository.findByTitleInAndGenre(strings, SysMenu.Genre.boss);
        // 数据库实际存在的默认系统菜单数目不匹配时,进行重新添加系统菜单
        if(sysMenus == null || sysMenus.size() != strings.size()){
            if(sysMenus == null) {
                sysMenus = new ArrayList<>();
            }
            sysMenuRepository.deleteAll(sysMenus);
            sysMenus.clear();

            // 系统主菜单
            SysMenu sysMenu1 = new SysMenu(SysMenu.Genre.boss,1L,0,"sysManage", SysMenu.Status.on,true,"系统", SysMenu.Type.list,nullSysMenu);
            // 系统子菜单
            SysMenu sysMenu2 = new SysMenu(SysMenu.Genre.boss, 2L,1,"userList", SysMenu.Status.on,true,"用户管理", SysMenu.Type.param,sysMenu1);
            SysMenu sysMenu3 = new SysMenu(SysMenu.Genre.boss, 2L,2,"roleList", SysMenu.Status.on,true,"角色管理", SysMenu.Type.param,sysMenu1);
            SysMenu sysMenu4 = new SysMenu(SysMenu.Genre.boss, 2L,3,"sysmenuList", SysMenu.Status.on,true,"菜单管理", SysMenu.Type.param,sysMenu1);
            sysMenus.add(sysMenu1);
            sysMenus.add(sysMenu2);
            sysMenus.add(sysMenu3);
            sysMenus.add(sysMenu4);
            /// 系统子菜单按钮
//            SysMenu sysMenu5 = new SysMenu(SysMenu.Genre.boss, 3L,1,"sysmenuList:add", SysMenu.Status.on,true,"菜单添加", SysMenu.Type.button,sysMenu4);
//            SysMenu sysMenu6 = new SysMenu(SysMenu.Genre.boss, 3L,1,"sysmenuList:edit", SysMenu.Status.on,true,"菜单修改", SysMenu.Type.button,sysMenu4);
//            SysMenu sysMenu7 = new SysMenu(SysMenu.Genre.boss, 3L,1,"sysmenuList:del", SysMenu.Status.on,true,"菜单删除", SysMenu.Type.button,sysMenu4);
//            sysMenus.add(sysMenu5);
//            sysMenus.add(sysMenu6);
//            sysMenus.add(sysMenu7);
            sysMenuRepository.saveAll(sysMenus);
        }
    }
    /** 系统菜单, 初始化时菜单集合 */
    private List<String> getStrings() {
        List<String> strings = new ArrayList<>();
        strings.add("系统");
        strings.add("用户管理");
        strings.add("角色管理");
        strings.add("菜单管理");
        return strings;
    }

    /**
     * 生成 顶级管理员
     */
    private void initUser() {
        BossUser bossUser = dao.get(BossUser.class, Constant.ADMIN_ID);
        if (null == bossUser) {
            // 超级管理员, 默认属于系统自动生成的顶级 组织部门
            bossUser = new BossUser(Constant.ADMIN_CODE, "超级管理员", "超级管理员", sysUserService.getPassword(Constant.DEFAULT_PASS_WORD),
                    BossUser.Status.on, AbstractEntity.generyDatetimeAndRandomNum(ORDERS_SUFF_COUNT), sysSectionService.getNumberOne());

            dao.save(bossUser);
        }
    }

    /**
     * 生成系统默认角色, 且给admin账号绑定超级管理员角色
     */
    public void initUserRole(){
        ArrayList<SysRole> rolesBySave = new ArrayList<>();
        // 获取需要系统自动生成 角色集合
        List<SysRole> getRoleList = sysRoleRepository.findByCodeIn(Constant.ROLE_CODE_LIST);
        List<String> roleList = new ArrayList<>();
        for (SysRole role : getRoleList) { roleList.add(role.getCode()); }

        // 生成默认角色
        for (SysRole.RoleInit roleInit : Constant.ROLE_LIST) {
            if(ListUtils.listIn(roleInit.getCode(), roleList) == -1) {
                SysRole sysRole = new SysRole(roleInit.getRoleName(), roleInit.getCode(), roleInit.getRemark(), SysRole.Status.on, roleInit.getDeleted());
                // 设置角色所属, 系统生成角色, 都属于系统自动生成的顶级 组织部门
                sysRole.setDept(sysSectionService.getNumberOne());
                if(roleInit.getCode().equals(Constant.ROLE_LIST.get(0).getCode())) {
                    // admin角色时, 自动绑定超级管理员账号
                    SysRole save = sysRoleRepository.save(sysRole);

                    BossUser adminUser = dao.get(BossUser.class, Constant.ADMIN_ID);
                    if (null == adminUser) {
                        initUser();
                        adminUser = dao.get(BossUser.class, Constant.ADMIN_ID);
                    }
                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setSysRole(save);
                    sysUserRole.setSysUser(adminUser);
                    sysUserRoleRepository.save(sysUserRole);
                }else {
                    rolesBySave.add(sysRole);
                }
            }
        }
        dao.saveOrModifyList(rolesBySave);
    }

    /** 超级管理员角色, 关联系统默认生成菜单 */
    public void initRoleMenu(){
        SysRoleMenu sysRoleMenu = dao.get(SysRoleMenu.class, Constant.ADMIN_ID);
        if(null == sysRoleMenu){
            // 获取系统默认生成所有菜单
            List<String> strings = getStrings();
            List<SysMenu> sysMenus = sysMenuRepository.findByTitleInAndGenre(strings, SysMenu.Genre.boss);
            if(sysMenus == null || sysMenus.size() != strings.size()){
                if(sysMenus == null) {
                    sysMenus = new ArrayList<>();
                }
                sysMenus.clear();
                initSysMenu();
                sysMenus = sysMenuRepository.findByTitleInAndGenre(strings, SysMenu.Genre.boss);
            }

            // 超级管理员角色关联, 系统默认生成订单
            List<SysRoleMenu> sysRoleMenus = new ArrayList<>();
            // 超级管理员角色
            SysRole role = dao.get(SysRole.class, Constant.ADMIN_ID);
            for (SysMenu sysMenu : sysMenus) {
                sysRoleMenu = new SysRoleMenu(role, sysMenu);
                sysRoleMenus.add(sysRoleMenu);
            }

            sysRoleMenuRepository.saveAll(sysRoleMenus);
        }
    }

    /** 生成 NullCategory 类别顶级对象 */
    private void initNullCategory() {
        List<NullCategory> categories = nullCategoryRepository.findAll();
        if (categories.isEmpty()) {
            NullCategory category = new NullCategory();
            J2CacheUtils.put("NullCategory", nullCategoryRepository.save(category));
            return;
        }
        J2CacheUtils.put("NullCategory", categories.get(0));
    }

    /** 生成 NullSysMacro(字典) 顶级对象 */
    private void initNullSysMacro() {
        List<NullSysMacro> macros = nullSysMacroRepository.findAll();
        if (macros.isEmpty()) {
            NullSysMacro nullSysMacro = new NullSysMacro();
            J2CacheUtils.put("NullSysMacro", nullSysMacroRepository.save(nullSysMacro));
            return;
        }
        J2CacheUtils.put("NullSysMacro", macros.get(0));
    }

    /** 生成主模板对象 */
    public EvaluationTemplate initEvaluationTemplate() {
        // 生成 评价模板 柱模板对象
        Map<String, Object> query = new HashMap<>(16);
        query.put("name", Constant.EVALUATIONTEMPLATE_NAME);
        List<EvaluationTemplate> list = dao.find(dao.query2Hql(EvaluationTemplate.class, query), query);
        if (list.isEmpty()) {
            EvaluationTemplate evaluationTemplate = new EvaluationTemplate();
            evaluationTemplate.setName(Constant.EVALUATIONTEMPLATE_NAME);
            evaluationTemplate.setSort(0L);
            dao.save(evaluationTemplate);

            return evaluationTemplate;
        }else {
            if(list.size() > 1) {
                throw new AdminException("查询出多个同名主模板");
            }
        }
        return list.get(0);
    }

    /** 深层 NullSysRegion 地区 顶级对象 */
    private void initNullSysRegion(){
        List<NullSysRegion> nullSysRegions =nullSysRegionRepository.findAll();
        if(nullSysRegions.isEmpty()){
            NullSysRegion nullSysRegion = new NullSysRegion();
            J2CacheUtils.put("NullSysRegion", nullSysRegionRepository.save(nullSysRegion));
            return;
        }
        J2CacheUtils.put("NullSysRegion", nullSysRegions.get(0));
    }
    /** 生成地区列表缓存 */
    private void initRegion() {
        sysRegionEntityList = dao.find("select s from SysRegion s");
        if (!sysRegionEntityList.isEmpty()) {
            J2CacheUtils.put(CacheConstant.REGION_CACHE_KEY, sysRegionEntityList);
        }
    }

    public void initTrackRateSet(){
        List<TrackGenerateRateSet> list = trackGenerateRateSetRepository.findAll();
        if(list.isEmpty()){
            TrackGenerateRateSet set = new TrackGenerateRateSet();
            TrackGenerateRateSet set1 = new TrackGenerateRateSet();
            set.setDayNum(30L);
            set.setExpression("0 4 1 1 * ?");
            set.setStatus(TrackGenerateRateSet.SetStatus.generate);
            set1.setDayNum(7L);
            set1.setExpression("0 0 0 1/7 * ? ");
            set1.setStatus(TrackGenerateRateSet.SetStatus.overtime);
            list.add(set);
            list.add(set1);
            trackGenerateRateSetRepository.saveAll(list);
        }
    }

}
